Rough but working .an1 support
authorparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 6 Apr 2005 04:57:23 +0000 (04:57 +0000)
committerparkrrrr <parkrrrr@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 6 Apr 2005 04:57:23 +0000 (04:57 +0000)
gpsbabel/Makefile
gpsbabel/README
gpsbabel/an1.c [new file with mode: 0644]
gpsbabel/defs.h
gpsbabel/route.c
gpsbabel/vecs.c
gpsbabel/waypt.c

index 1bbd6f5904bc5593ef7da96a55545268046ebd1c..50fdc9e60ffe34c21b4b20ad662727f9c350edf4 100644 (file)
@@ -27,7 +27,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \
        gpilots.o saroute.o navicache.o psitrex.o geoniche.o delgpl.o \
        ozi.o nmea.o text.o html.o palmdoc.o netstumbler.o hsa_ndv.o \
        igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \
-       vcf.o overlay.o kml.o google.o lowranceusr.o
+       vcf.o overlay.o kml.o google.o lowranceusr.o an1.o
 
 FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o
 
@@ -124,6 +124,7 @@ mac-release:
 
 # Machine generated from here down.  
 
+an1.o: an1.c defs.h queue.h gbtypes.h
 arcdist.o: arcdist.c defs.h queue.h gbtypes.h grtcirc.h
 brauniger_iq.o: brauniger_iq.c defs.h queue.h gbtypes.h jeeps/gpsserial.h \
   jeeps/gps.h jeeps/gpsport.h jeeps/gpssend.h jeeps/gpsread.h \
@@ -319,4 +320,3 @@ shapelib/dbfopen.o: shapelib/dbfopen.c shapelib/shapefil.h
 shapelib/shpopen.o: shapelib/shpopen.c shapelib/shapefil.h
 internal_styles.c: mkstyle.sh style/README.style style/arc.style style/csv.style style/custom.style style/dna.style style/fugawi.style style/gpsdrive.style style/gpsman.style style/mapconverter.style style/mxf.style style/nima.style style/s_and_t.style style/saplus.style style/tabsep.style style/xmap.style style/xmapwpt.style
        ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)
-       ./mkstyle.sh > internal_styles.c || (rm -f internal_styles.c ; exit 1)
index d7b0d8538d5280654dfdf98f7c890aa79630527a..2af698072aca584332f096a20ef4177613c73d43 100644 (file)
@@ -773,6 +773,22 @@ THE FORMATS
 
         gpsbabel -i google -f google_map.js -o gpx -F google_map.gpx
 
+    AN1
+
+        This format supports the DeLorme ".an1" drawing file format.  It
+        can currently be used to either read or write drawing files.  If
+        you use this format to create drawing files with routes or waypoints
+        from another source, it will currently create "Red Flag" symbols 
+        for waypoints, and thick red lines for routes or tracks.  It is
+        possible to merge two drawing layers by doing something like this:
+
+        gpsbabel -i an1 -f one.an1 -f two.an1 -o an1 -F merged.an1
+
+        Currently, GPSBabel only writes drawing layers.  If your input
+        file is a road, track, trail, or waypoint layer, you should not
+        attempt to write to an .an1 file as the results may be 
+        unpredictable. 
+
 DATA FILTERS
 
        GPSBabel supports data filtering.  Data filters are invoked from
diff --git a/gpsbabel/an1.c b/gpsbabel/an1.c
new file mode 100644 (file)
index 0000000..739cfb5
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+    Read DeLorme drawing files (.an1)
+    Copyright (C) 2005 Ron Parker and Robert Lipe.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MYNAME "an1"
+#include "defs.h"
+
+FILE *infile;
+FILE *outfile;
+
+static char *output_type = NULL;
+long output_type_num = 0;
+
+static long serial=10000;
+static long rtserial=1;
+
+static
+arglist_t an1_args[] = {
+       {"type", &output_type, "Type of .an1 file (0=drawing)", 
+               "0", ARGTYPE_HIDDEN | ARGTYPE_INT },
+       {0, 0, 0, 0 }
+};
+
+static unsigned short
+ReadShort(FILE * f)
+{
+       gbuint16 result = 0;
+
+       fread(&result, sizeof (result), 1, f);
+       return le_read16(&result);
+}
+
+static void 
+WriteShort(FILE * f, unsigned short s)
+{
+       gbuint16 tmp = 0;
+        le_write16( &tmp, s );
+       fwrite( &tmp, sizeof(tmp), 1, f );
+}
+
+static unsigned long
+ReadLong(FILE * f)
+{
+       gbuint32 result = 0;
+
+       fread(&result, sizeof (result), 1, f);
+       return le_read32(&result);
+}
+
+static void 
+WriteLong(FILE * f, unsigned long l)
+{
+       gbuint32 tmp = 0;
+        le_write32( &tmp, l );
+       
+       fwrite( &tmp, sizeof(tmp), 1, f );
+}
+
+static double
+ReadDouble( FILE * f )
+{
+       double tmp = 0;
+       double result = 0;
+       fread(&tmp, sizeof(tmp),1,f);
+       le_read64(&result, &tmp );
+       return result;
+}
+
+static void 
+WriteDouble(FILE * f, double d)
+{
+       double tmp = 0;
+        le_read64( &tmp, (void *)&d );
+       fwrite( &tmp, sizeof(tmp), 1, f );
+}
+
+static char *
+ReadString( FILE * f, short len ) 
+{
+       char *result = NULL;
+       result = (char *)xcalloc( 1, len + 1 );
+       if ( len ) {
+               fread( result, 1, len, f );
+       }
+       return result;
+}
+
+static unsigned char
+ReadChar( FILE *f )
+{
+       unsigned char result = 0;
+       fread( &result, 1, 1, f );
+       return result;
+}
+
+static void
+WriteChar( FILE *f, unsigned char c ) 
+{
+       fwrite( &c, 1, 1, f );
+}
+
+static void
+WriteString( FILE *f, char *s )
+{
+       fwrite( s, 1, strlen(s), f );
+}
+
+static void
+Skip(FILE * f,
+     unsigned long distance)
+{
+       fseek(f, distance, SEEK_CUR);
+}
+
+static double
+DecodeOrd( long ord )
+{
+       return (double)(0x80000000-ord)/(0x800000);
+}
+
+static long
+EncodeOrd( double ord )
+{
+       unsigned long tmp = ord * 0x800000;
+       return 0x80000000UL-tmp;
+}
+
+typedef struct {
+       short hotspotxhi;
+       long hotspoty;
+       long unk1;
+       unsigned long guid[4];
+       char *name;
+} an1_symbol_record;
+
+typedef struct {
+       an1_base base;
+       short magic;
+       long unk1;
+       long lon;
+       long lat;
+       short type;
+       long height;
+       long width;
+       short unk2;
+       short unk3;
+       short serial;
+       short unk4;
+       unsigned char create_zoom;
+       unsigned char visible_zoom;
+       short unk5;
+       double radius;
+       char *name;
+       char *fontname;
+       long guid[4];
+       long fontcolor;
+       long fontstyle;
+       long fontsize;
+       long outlineweight;
+       long outlinecolor;
+       long outlineflags;
+       long fillcolor;
+       long unk6;
+       long fillflags;
+} an1_waypoint_record;
+
+typedef struct {
+       an1_base base;
+       short magic;
+       long unk0;
+       long lon;
+       long lat;
+       short unk1;
+} an1_vertex_record;
+
+typedef struct {
+       an1_base base;
+       short magic;
+       short unk1;
+       short serial;
+       long unk2;
+       short unk3;
+       short type;
+       long unk4;
+       char *name;
+       long lineweight;
+       long linestyle;
+       long linecolor;
+       long unk5;
+       long polyfillcolor;
+       long unk6;
+       long unk7;
+       short unk8;
+       long pointcount;
+} an1_line_record;
+
+static an1_waypoint_record *Alloc_AN1_Waypoint( );
+
+void Destroy_AN1_Waypoint( void *vwpt ) {
+       an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt;
+       xfree( wpt->name );
+       xfree( wpt->fontname );
+}
+
+void Copy_AN1_Waypoint( void **vdwpt, void *vwpt ) {
+       an1_waypoint_record *wpt = (an1_waypoint_record *)vwpt;
+       an1_waypoint_record *dwpt = Alloc_AN1_Waypoint();
+       memcpy( dwpt, wpt, sizeof( an1_waypoint_record ));
+       dwpt->name = xstrdup( wpt->name );
+       dwpt->fontname = xstrdup( wpt->fontname );
+       *vdwpt = (void *)dwpt;
+}
+
+static an1_waypoint_record *Alloc_AN1_Waypoint( ) {
+       an1_waypoint_record *result = NULL;
+       result = (an1_waypoint_record *)xcalloc( sizeof(*result), 1 );
+       result->base.copy = Copy_AN1_Waypoint;
+       result->base.destroy = Destroy_AN1_Waypoint; 
+}
+       
+static an1_vertex_record *Alloc_AN1_Vertex();
+
+void Destroy_AN1_Vertex( void *vvertex ) {
+       /* do nothing */
+}
+
+void Copy_AN1_Vertex( void **vdvert, void *vvert ) {
+       an1_vertex_record *vert = (an1_vertex_record *)vvert;
+       an1_vertex_record *dvert = Alloc_AN1_Vertex();
+       memcpy( dvert, vert, sizeof( an1_vertex_record ));
+       *vdvert = (void *)dvert;
+}
+
+static an1_vertex_record *Alloc_AN1_Vertex() {
+       an1_vertex_record *result = NULL;
+       result = (an1_vertex_record *)xcalloc( sizeof( *result), 1 );
+       result->base.copy = Copy_AN1_Vertex;
+       result->base.destroy = Destroy_AN1_Vertex;
+}
+                       
+
+static an1_line_record *Alloc_AN1_Line();
+
+void Destroy_AN1_Line( void *vline ) {
+       an1_line_record *line = (an1_line_record *)vline;
+       xfree( line->name );
+}
+
+void Copy_AN1_Line( void **vdline, void *vline ) {
+       an1_line_record *line = (an1_line_record *)vline;
+       an1_line_record *dline = Alloc_AN1_Line();
+       memcpy( dline, line, sizeof( an1_line_record ));
+       dline->name = xstrdup( line->name );
+       *vdline = (void *)dline;
+}
+
+static an1_line_record *Alloc_AN1_Line( ) {
+       an1_line_record *result = NULL;
+       result = (an1_line_record *)xcalloc( sizeof(*result), 1 );
+       result->base.copy = Copy_AN1_Line;
+       result->base.destroy = Destroy_AN1_Line;
+}
+
+
+static void Destroy_AN1_Symbol( an1_symbol_record *symbol ) {
+       xfree( symbol->name );
+}
+
+static void Read_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) {
+       short len;
+       
+       wpt->magic = ReadShort( f );
+       wpt->unk1 = ReadLong( f );
+       wpt->lon = ReadLong( f );
+       wpt->lat = ReadLong( f );
+       wpt->type = ReadShort( f );
+       wpt->height = ReadLong( f );
+       wpt->width = ReadLong( f );
+       wpt->unk2 = ReadShort( f );
+       wpt->unk3 = ReadShort( f );
+       wpt->serial = ReadShort( f );
+       wpt->unk4 = ReadShort( f );
+       wpt->create_zoom = ReadChar( f );
+       wpt->visible_zoom = ReadChar( f );
+       wpt->unk5 = ReadShort( f );
+       wpt->radius = ReadDouble( f );
+        len = ReadShort( f );
+        wpt->name = ReadString( f, len );
+        len = ReadShort( f );
+        wpt->fontname = ReadString( f, len );
+        for ( len = 0; len < 4; len++ ) 
+               wpt->guid[len] = ReadLong( f );
+        wpt->fontcolor = ReadLong( f );
+       wpt->fontstyle = ReadLong( f );
+       wpt->fontsize = ReadLong( f );
+       wpt->outlineweight = ReadLong( f );
+       wpt->outlinecolor = ReadLong( f );
+       wpt->outlineflags = ReadLong( f );
+       wpt->fillcolor = ReadLong( f );
+       wpt->unk6 = ReadLong( f );
+       wpt->fillflags = ReadLong( f ); 
+}
+
+static void Write_AN1_Waypoint( FILE *f, an1_waypoint_record *wpt ) {
+       short len;
+       
+       WriteShort( f, wpt->magic );
+       WriteLong( f, wpt->unk1 );
+       WriteLong( f, wpt->lon );
+       WriteLong( f, wpt->lat );
+       WriteShort( f, wpt->type );
+       WriteLong( f, wpt->height );
+       WriteLong( f, wpt->width );
+       WriteShort( f, wpt->unk2 );
+       WriteShort( f, wpt->unk3 );
+       WriteShort( f, wpt->serial );
+       WriteShort( f, wpt->unk4 );
+       WriteChar( f, wpt->create_zoom );
+       WriteChar( f, wpt->visible_zoom );
+       WriteShort( f, wpt->unk5 );
+       WriteDouble( f, wpt->radius );
+       len = strlen( wpt->name );
+       WriteShort( f, len );
+        WriteString( f, wpt->name );
+       len = strlen( wpt->fontname );
+       WriteShort( f, len );
+        WriteString( f, wpt->fontname );
+        for ( len = 0; len < 4; len++ ) 
+               WriteLong( f, wpt->guid[len] );
+        WriteLong( f, wpt->fontcolor );
+       WriteLong( f, wpt->fontstyle );
+       WriteLong( f, wpt->fontsize );
+       WriteLong( f, wpt->outlineweight );
+       WriteLong( f, wpt->outlinecolor );
+       WriteLong( f, wpt->outlineflags );
+       WriteLong( f, wpt->fillcolor );
+       WriteLong( f, wpt->unk6 );
+       WriteLong( f, wpt->fillflags ); 
+}
+
+static void Read_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) {
+       
+       vertex->magic = ReadShort( f );
+       vertex->unk0 = ReadLong( f );
+       vertex->lon = ReadLong( f );
+       vertex->lat = ReadLong( f );
+       vertex->unk1 = ReadShort( f );
+}
+
+static void Write_AN1_Vertex( FILE *f, an1_vertex_record *vertex ) {
+       WriteShort( f, vertex->magic );
+       WriteLong( f, vertex->unk0 );
+       WriteLong( f, vertex->lon );
+       WriteLong( f, vertex->lat );
+       WriteShort( f, vertex->unk1 );
+}
+
+static void Read_AN1_Line( FILE *f, an1_line_record *line ) {
+       
+       short len;
+       
+       line->magic = ReadShort( f );
+       line->unk1 = ReadShort( f );
+       line->serial = ReadShort( f );
+       line->unk2 = ReadLong( f );
+       line->unk3 = ReadShort( f );
+       line->type = ReadShort( f );
+       line->unk4 = ReadLong( f );
+       len = ReadShort( f );
+       line->name = ReadString( f, len );
+       line->lineweight = ReadShort( f );
+       line->linestyle = ReadLong( f );
+       line->linecolor = ReadLong( f );
+       line->unk5 = ReadLong( f );
+       line->polyfillcolor = ReadLong( f );
+       line->unk6 = ReadLong( f );
+       line->unk7 = ReadLong( f );
+       line->unk8 = ReadShort( f );
+       line->pointcount = ReadLong( f );
+}
+
+static void Write_AN1_Line( FILE *f, an1_line_record *line ) {
+       short len;
+       
+       WriteShort( f, line->magic );
+       WriteShort( f, line->unk1 );
+       WriteShort( f, line->serial );
+       WriteLong( f, line->unk2 );
+       WriteShort( f, line->unk3 );
+       WriteShort( f, line->type );
+       WriteLong( f, line->unk4 );
+       len = strlen( line->name );
+       WriteShort( f, len );
+       WriteString( f, line->name );
+       WriteShort( f, line->lineweight );
+       WriteLong( f, line->linestyle );
+       WriteLong( f, line->linecolor );
+       WriteLong( f, line->unk5 );
+       WriteLong( f, line->polyfillcolor );
+       WriteLong( f, line->unk6 );
+       WriteLong( f, line->unk7 );
+       WriteShort( f, line->unk8 );
+       WriteLong( f, line->pointcount );
+} 
+
+static void Skip_AN1_IL( FILE *f ) {
+       Skip( f, 26 );
+}
+
+static void Skip_AN1_BM( FILE *f ) {
+       unsigned long bmsize;
+       unsigned long palettesize;
+       unsigned long bmisize;
+       unsigned long bitoffset;
+       
+       Skip( f, 8 );  /* BITMAPFILEHEADER fields 1-3 */
+       bitoffset = ReadLong( f );
+       
+       bmisize = ReadLong( f );
+       Skip( f, 16 );  /* BITMAPINFOHEADER fields 2-6 */
+       bmsize = ReadLong( f );
+       Skip( f, 16 );  /* BITMAPINFOHEADER fields 8-11 */
+       
+       palettesize = bitoffset - bmisize - 14;
+       Skip( f, bmsize + palettesize );
+}
+
+static void Read_AN1_Symbol( FILE *f, an1_symbol_record *symbol ) {
+       short len;
+
+       /* This is just the high word of a long; we ate the low 
+        * word in the caller.  Fortunately, we don't care. */
+       symbol->hotspotxhi = ReadShort( f );
+       symbol->hotspoty = ReadLong( f );
+       symbol->unk1 = ReadLong( f );
+       for ( len = 0; len < 4; len++ ) {
+               symbol->guid[len] = ReadLong( f );
+       }
+       len = ReadChar( f );
+       symbol->name = ReadString( f, len );
+}
+
+static void Read_AN1_Header( FILE *f ) {
+       unsigned short magic;
+       unsigned short type;
+       
+       magic = ReadShort( f );
+       type = ReadShort( f );
+}
+
+static void Write_AN1_Header( FILE *f ) {
+       WriteShort( f, 11557 );
+       WriteShort( f, atoi( output_type ) );
+}
+
+static void Read_AN1_Bitmaps( FILE *f ) {
+       long count;
+       unsigned short magic;
+       an1_symbol_record symbol;
+       
+       count = ReadLong( f );
+       
+       while ( count ) {
+               magic = ReadShort( f );
+               switch (magic) {
+                       case 0x4d42:
+                               Skip_AN1_BM( f );
+                               break;
+                       case 0x4c49:
+                               Skip_AN1_IL( f );
+                               break;
+                       default:
+                               Read_AN1_Symbol( f, &symbol );
+                               Destroy_AN1_Symbol( &symbol );
+                               count--;
+                               break;
+               }
+       }
+                                               
+       /* Read the symbol table */
+}
+
+static void Write_AN1_Bitmaps( FILE *f ) {
+       /* On write, we don't output any bitmaps, so writing them
+        * is just a matter of writing a count of zero */
+       WriteLong( f, 0 );
+}
+
+static void Read_AN1_Waypoints( FILE *f ) {
+       unsigned long count = 0;
+       unsigned long i = 0;
+       an1_waypoint_record *rec = NULL;
+       waypoint *wpt_tmp;
+       ReadShort( f );
+       count = ReadLong( f );
+       for (i = 0; i < count; i++ ) {
+               rec = Alloc_AN1_Waypoint();
+               Read_AN1_Waypoint( f, rec );
+               wpt_tmp = waypt_new();
+               
+               wpt_tmp->longitude = -DecodeOrd( rec->lon );
+               wpt_tmp->latitude = DecodeOrd( rec->lat );
+               wpt_tmp->description = xstrdup( rec->name );
+               wpt_tmp->an1_extras = (an1_base *)(void *)rec;
+               rec = NULL;
+               waypt_add( wpt_tmp );
+       }
+}
+
+static void
+Write_One_AN1_Waypoint( const waypoint *wpt )
+{
+       an1_waypoint_record *rec;
+       int local;
+       
+       if ( wpt->an1_extras ) {
+               rec = (an1_waypoint_record *)(void *)(wpt->an1_extras); 
+               xfree( rec->name );
+               local = 0;
+       }
+       else {
+               rec = Alloc_AN1_Waypoint();
+               local = 1;
+               rec->magic = 1;
+               rec->type = 1;
+               rec->unk2 = 3;
+               rec->unk3 = 18561;
+               rec->fontname = xstrdup( "Arial" );
+               rec->guid[0] = 1648238304;
+               rec->guid[1] = 299085607;
+               rec->guid[2] = 1342187964;
+               rec->guid[3] = 854917636;
+               rec->fontsize = 10;
+       }
+       rec->name = xstrdup( wpt->description );
+       rec->lat = EncodeOrd( wpt->latitude );
+       rec->lon = EncodeOrd( -wpt->longitude );
+       rec->serial = serial++;
+       
+       Write_AN1_Waypoint( outfile, rec );
+       if ( local ) {
+               Destroy_AN1_Waypoint( rec );
+               xfree( rec );
+       }
+}
+
+static void Write_AN1_Waypoints( FILE *f ) {
+       WriteShort( f, 2 );
+       WriteLong( f, waypt_count() );
+       waypt_disp_all( Write_One_AN1_Waypoint );
+}
+
+static void Read_AN1_Lines( FILE *f ) {
+       unsigned long count = 0;
+       unsigned long i = 0;
+       unsigned long j = 0;
+       an1_line_record *rec = NULL;
+       an1_vertex_record *vert = NULL;
+        route_head *rte_head;
+        waypoint *wpt_tmp;
+
+       ReadShort( f );
+       count = ReadLong( f );
+       for (i = 0; i < count; i++ ) {
+               rec = Alloc_AN1_Line();
+               Read_AN1_Line( f, rec );
+               /* create route rec */
+                rte_head = route_head_alloc();
+               rte_head->an1_extras = (an1_base *)(void *)rec;
+                route_add_head(rte_head);
+               for (j = 0; j < rec->pointcount; j++ ) {
+                       vert = Alloc_AN1_Vertex();
+                       Read_AN1_Vertex( f, vert );
+                       
+                       /* create route point */
+                       wpt_tmp = waypt_new();
+                        wpt_tmp->latitude = DecodeOrd( vert->lat );
+                       wpt_tmp->longitude = -DecodeOrd( vert->lon );
+                       wpt_tmp->shortname = (char *) xmalloc(7);
+                       sprintf( wpt_tmp->shortname, "\\%5.5x", rtserial++ );
+                       wpt_tmp->an1_extras = (an1_base *)(void *)vert;
+                       route_add_wpt(rte_head, wpt_tmp);
+               }
+       }
+}
+
+static void
+Write_One_AN1_Line( const route_head *rte )
+{
+       an1_line_record *rec;
+       int local;
+       
+       if ( rte->an1_extras ) {
+               rec = (an1_line_record *)(void *)(rte->an1_extras);     
+               local = 0;
+       }
+       else {
+               rec = Alloc_AN1_Line();
+               local = 1;
+               switch (output_type_num) {
+                       /*  drawing road trail waypoint track  */
+                       case 1: /* road */
+                               rec->magic = 4112;
+                               rec->unk1 = 4359;
+                               rec->unk2 = 655360;
+                               rec->type = 14;
+                               rec->unk8 = 2;
+                               break;
+                               
+                       case 2: /* trail */
+                               rec->magic = 7248;
+                               rec->unk1 = 4359;
+                               rec->unk2 = 917504;
+                               rec->type = 15;
+                               rec->unk8 = 2;
+                               break;
+                               
+                       case 4: /* track */
+                               rec->magic = 21;
+                               rec->unk1 = 18560;
+                               rec->unk2 = 917504;
+                               rec->type = 16;
+                               rec->unk4 = 2;
+                               rec->unk8 = 2;
+                               break;
+                               
+                       case 0: /* drawing */
+                       case 3: /* waypoint - shouldn't have lines */
+                       default:
+                               rec->magic = 21;
+                               rec->unk1 = 18560;
+                               rec->unk2 = 1048576;
+                               rec->type = 2;
+                               rec->unk4 = 2;
+                               rec->lineweight = 6;
+                               rec->linecolor = 255; /* red */
+                               rec->unk5 = 3;
+                               rec->unk8 = 2;
+                               break;
+               }
+               rec->name = xstrdup( "" );
+                               
+       }
+       rec->serial = serial++;
+       rec->pointcount = rte->rte_waypt_ct;    
+       Write_AN1_Line( outfile, rec );
+       if ( local ) {
+               Destroy_AN1_Line( rec );
+               xfree( rec );
+       }
+}
+
+static void
+Write_One_AN1_Vertex( const waypoint *wpt )
+{
+       an1_vertex_record *rec;
+       int local;
+       
+       if ( wpt->an1_extras ) {
+               rec = (an1_vertex_record *)(void *)(wpt->an1_extras);   
+               local = 0;
+       }
+       else {
+               rec = Alloc_AN1_Vertex();
+               local = 1;
+               rec->magic = 1;
+       }
+       rec->lat = EncodeOrd( wpt->latitude );
+       rec->lon = EncodeOrd( -wpt->longitude );
+       
+       Write_AN1_Vertex( outfile, rec );
+       if ( local ) {
+               Destroy_AN1_Vertex( rec );
+               xfree( rec );
+       }
+}
+
+static void Write_AN1_Lines( FILE *f ) {
+       WriteShort( f, 2 );
+       WriteLong( f, route_count()+track_count() );
+       
+       route_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex );
+       track_disp_all( Write_One_AN1_Line, NULL, Write_One_AN1_Vertex );
+}
+
+static void
+rd_init(const char *fname)
+{
+       infile = xfopen(fname, "rb", MYNAME);
+       output_type_num = atoi( output_type );
+}
+
+static void
+rd_deinit(void)
+{
+       fclose(infile);
+}
+
+static void
+my_read(void)
+{
+       Read_AN1_Header( infile );
+       Read_AN1_Bitmaps( infile );
+       Read_AN1_Waypoints( infile );
+       Read_AN1_Lines( infile );
+}
+
+static void
+wr_init(const char *fname)
+{
+       outfile = xfopen( fname, "wb", MYNAME );
+       output_type_num = atoi( output_type );
+}
+
+static void
+wr_deinit( void ) 
+{
+       fclose(outfile);
+}
+
+static void
+my_write( void ) 
+{
+       Write_AN1_Header( outfile );
+       Write_AN1_Bitmaps( outfile );
+       Write_AN1_Waypoints( outfile );
+       Write_AN1_Lines( outfile );
+}
+
+ff_vecs_t an1_vecs = {
+       ff_type_file,
+       FF_CAP_RW_ALL,
+       rd_init,
+       wr_init,
+       rd_deinit,
+       wr_deinit,
+       my_read,
+       my_write,
+       NULL, 
+       an1_args
+};
index 93eaa0c19482b9f91479943dc56e6781c44650cb..ae933b01fad5a8471cda237501bd2cce4eccb54e 100644 (file)
@@ -151,6 +151,13 @@ typedef struct xml_tag {
        struct xml_tag *child;
 } xml_tag ;
 
+typedef void (*an1_destroy)(void *);
+typedef void (*an1_copy)(void **, void *);
+typedef struct {
+       an1_destroy destroy;
+       an1_copy copy;
+} an1_base;
+
 /*
  * This is a waypoint, as stored in the GPSR.   It tries to not 
  * cater to any specific model or protocol.  Anything that needs to
@@ -214,11 +221,14 @@ typedef struct {
         * This causes it to be removed last.
         * This is currently used by the saroute input filter to give named
         * waypoints (representing turns) a higher priority.
+        * This is also used by the google input filter because they were
+        * nice enough to use exactly the same priority scheme.
         */
        int route_priority;
        
        geocache_data gc_data;
        xml_tag *gpx_extras;
+       an1_base *an1_extras;
        void *extra_data;       /* Extra data added by, say, a filter. */
 } waypoint;
 
@@ -229,6 +239,7 @@ typedef struct {
        char *rte_desc;
        int rte_num;
        int rte_waypt_ct;               /* # waypoints in waypoint list */
+       an1_base *an1_extras;
 } route_head;
 
 /*
index b06ce2bb813f0f1d975abcf88b787a19ddce3c02..545da82107dba7ce778f423a0e4ae249d4f25a45 100644 (file)
@@ -128,6 +128,10 @@ route_free(route_head *rte)
        }
        rte_waypts -= rte->rte_waypt_ct;
        waypt_flush(&rte->waypoint_list);
+        if ( rte->an1_extras ) {
+                (*(rte->an1_extras->destroy))((void *)rte->an1_extras );
+                xfree( rte->an1_extras );
+        }
        xfree(rte);
 }
 
index c67cfd06e67413a2cf1302733d4b996fe511f0a2..42734e795ca2843ee78e7d8ef2876823e18aa1b6 100644 (file)
@@ -76,6 +76,7 @@ extern ff_vecs_t vcf_vecs;
 extern ff_vecs_t overlay_vecs;
 extern ff_vecs_t kml_vecs;
 extern ff_vecs_t google_vecs;
+extern ff_vecs_t an1_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -356,6 +357,12 @@ vecs_t vec_list[] = {
                "Google Maps XML",
                "xml"
        },
+       {
+               &an1_vecs,
+               "an1",
+               "DeLorme .an1 (drawing) file",
+               "an1"
+       },
        {
                NULL,
                NULL,
index ae15046f44cf728acf5e29d442bed112f2d86c1d..14305d98c7162b2b26d6e4a084c9d8b18e4722d1 100644 (file)
@@ -66,6 +66,10 @@ waypt_dupe(const waypoint *wpt)
         */
        tmp->Q.next = tmp->Q.prev = NULL;
        tmp->gpx_extras = NULL;
+       if ( wpt->an1_extras ) {
+               wpt->an1_extras->copy((void **)(&tmp->an1_extras), 
+                        (void *)wpt->an1_extras );
+       }
 
        return tmp;
 }
@@ -270,6 +274,10 @@ waypt_free( waypoint *wpt )
        if (wpt->gc_data.desc_long.utfstring) {
                xfree(wpt->gc_data.desc_long.utfstring);
        }
+       if ( wpt->an1_extras ) {
+               (*(wpt->an1_extras->destroy))((void *)wpt->an1_extras );
+               xfree( wpt->an1_extras );
+       }
        xfree(wpt);     
 }